home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Tool Chest / Development Kits / MPW etc. / Debuggers / SADE / SADE 1.4a3 / SADE Example Scripts / Resource < prev    next >
Encoding:
Text File  |  1992-07-10  |  11.7 KB  |  287 lines  |  [TEXT/sade]

  1. ##########################################################################################
  2. #    Symbolic Application Debugging Environment 1.4
  3. #
  4. #    copyright Apple Computer, Inc. 1987-1991
  5. #    All rights reserved.
  6. #
  7. ##########################################################################################
  8.  
  9. # --------------------------------------------------------------------------------------
  10. # to TRACE THE RESOURCE CHAIN AND DISPLAY RESOURCE MAP INFORMATION
  11. # select and enter all procs then execute:
  12. # resmap or resmap "rsrc" to see just info for specified resource type (case sensitive)
  13. # --------------------------------------------------------------------------------------
  14.     
  15. proc fileName(FileRefNum)
  16.     define FCBSPTr := $34E                                                                            
  17.     printf ("File Name: %P ", ^pstring (FCBSPtr^ + fileRefNum + 62)^)
  18. end
  19.  
  20.  
  21. proc ResName(nameOffset)
  22.     define resNamePtr    
  23.     ResNamePtr := NEXTresFile + (^Word(NEXTresFile + 26)^)        # get start of  name list
  24.     ResNamePtr := ResNamePtr + nameOffset                        # add offset into list for this resource.
  25.     printf("   name:%P ", ^pstring(resNamePtr)^)                              
  26. end
  27.  
  28.     
  29. proc ResInfo(refListPtr, numThisType)                    
  30.     define looper
  31.     define resId
  32.     define resAttributes
  33.     define resHandle
  34.     define resPtr
  35.     define nameOffset
  36.     
  37.     for looper := 0 to numThisType                                # show info for all resources of current type
  38.         resId := ^Word(refListPtr)^
  39.         printf("\n      ID: % 6d", resId)                        # info for each resource includes: resId
  40.         resHandle := (refListPtr + 8)^
  41.         if resHandle = 0 then                                    # if resource not in memory, say its at 0.
  42.             resPtr := 0                                                
  43.         else
  44.             resPtr := resHandle^                                # else give memory location where resource is loaded,
  45.         end            
  46.         if $80000000 & resPtr then                              # note if "locked" bit set in resource's master pointer
  47.             printf " *"
  48.         else 
  49.             printf "  "
  50.         end
  51.         resPtr := resPtr & $00ffffff              
  52.          printf("   at: %.8X", resPtr)
  53.         resAttributes := ^UnsignedByte(refListPtr + 4)^                        
  54.         printf ("  attribs: %.8b", resAttributes)                # resource  attributes as bit pattern
  55.  
  56.         nameOffset := ^Word(refListPtr+2)^
  57.         if nameOffset <> -1 then                                # one word offset to resource name from top of name list  
  58.             resName(nameOffset)                                    # if no name    offset is -1                        
  59.         end
  60.         refListPtr := refListPtr + 12
  61.     end
  62. end
  63.  
  64.  
  65. proc ResTypes (typeListPtr, targetType)
  66.     define numTypes    := ^Word(TypeListPtr)^
  67.     define numThisType
  68.     define looper
  69.     define thisResPtr
  70.     define refListPtr
  71.     
  72.     printf ("   Number of Resource types: %d\n", numTypes+1)    # number of resource types in current map    
  73.     for looper := 0 to NumTypes
  74.          ThisResPtr := (typeListPtr + 2) + (looper * 8)
  75.         if targetType = 0 || targetType = thisResPtr^ then        # If optional target type spec in call to ResMap
  76.             numThisType := ^Word(thisResPtr + 4)^                # show info only for that type, else show all types
  77.             printf("\n   type: %.4s  instances: %d", thisResPtr^, numThisType+1)
  78.             refListPtr := ^Word(thisResPtr + 6)^+typeListPtr    # find offset into Reference List for type from top of type list.  
  79.             ResInfo(refListPtr, numThisType)                    # get resource info for type.
  80.         end                
  81.     end        
  82. end    
  83.  
  84.  
  85.  
  86. proc ResMap targetType                    
  87.  
  88.     # Global Variables:
  89.     define global NEXTresFile                                    # pointer to top of current resource map
  90.  
  91.     define FileRef                                 
  92.     define typeList                            
  93.     
  94.     if Nargs = 0 then                                             # if optional target resource type not input, then show info for all types
  95.         targetType := 0                                            # else show info for target type only
  96.     end
  97.     NEXTresFile := @topMapHndl
  98.     printf "\nRESOURCE CHAIN - Top to bottom:"
  99.     while (NextResFile^ <> 0)                                    # display each resource map in the chain, starting from the top map
  100.  
  101.         NEXTresFile := NEXTresFile^^                        
  102.         
  103.         IF NEXTresFile = 0
  104.             printf "\nA resource map has been purged--a major problem!\n"
  105.             return
  106.         end
  107.  
  108.         fileRef := ^Word(NEXTresFile+20)^
  109.  
  110.         printf("\n\nResource map at: %.8X   File ref num: %X\n", NEXTresFile, fileRef)
  111.         fileName(fileRef)                                        # get file name
  112.         typeList := ^Word(NEXTresFile + 24)^
  113.  
  114.         ResTypes (NEXTresFile + typeList, targetType)            # get resource type info
  115.         NextresFile := NextresFile+16;
  116.     end                        
  117.     printf "\n"
  118.     undefine NEXTresFile                                        # pointer to top of current resource map
  119.  
  120. end
  121.  
  122.  
  123. ###############################################################################
  124.  
  125. func CheckMP (thisBlockHndl,thisZonePtr)
  126.     # function returns a result code of 1 if NotOk and 0 if all is well.
  127.     # verify that the handle is not NIL,  and that the master pointer is not odd and is located fully within this zone
  128.     # verify that the master pointer to the block in the resource map matches the 
  129.     # master pointer derived from the block's self relative handle    
  130.     define selfHndl
  131.     define endZone
  132.     define notOk := 0                                                    # assume all is well
  133.     
  134.     if thisBlockhndl = 0 then                                         # check handle in resource map for valid value
  135.         "\n## block has an invalid NIL handle"
  136.         notOk := 1
  137.     elseif  thisBlockHndl^ & $01 = 1 then 
  138.         "\n## block has an invalid odd master pointer"
  139.         notOk := 1
  140.     end                                                                    
  141.     endZone := thisZonePtr^^  & $00ffffff                    # yields size of zone trailer block 
  142.     endZone := thisZonePtr^ + endZone                            # pointer to zone trailer block plus its length is address of last byte in zone.    
  143.     if thisBlockHndl < thisZonePtr || thisBlockHndl + 4 > endZone then    
  144.         "\n## block's master pointer falls outside of this zone"
  145.         printf ("zone start %.8x - zone end %.8x - master pointer at %.8x\n",thisZonePtr, endZone, thisBlockHndl)
  146.         notOk := 1
  147.     end                                                                    
  148.     selfHndl := ((thisBlockHndl^ & $00ffffff )- 8 + 4)^    # yields offset from top ThisZonePtr to this block's master pointer
  149.     selfHndl :=  thisZonePtr + selfHndl                         # is location of  MP indicated by this block's self-relative handle
  150.     if selfHndl^ <> thisBlockHndl^ then     
  151.         "\n## block's self relative handle yields a  master pointer which doesn't match the master pointer in the resource map."
  152.         printf("self-relative MP %.8x - resource map MP %.8x   (high bytes intact)",  selfHndl^, thisBlockHndl^)
  153.         notOk := 1
  154.     end
  155.     return notOk
  156. end # func CheckMP
  157.  
  158.  
  159. func BlockInZone(thisBlockHndl, thisZonePtr)
  160.     # function returns a result code of 1 if NotOk and 0 if all is well
  161.     # verify that this block starts in this zone and doesn't extend beyond it
  162.     # also verify that the block size is not 0 or odd
  163.     define endZone
  164.     define blockSize
  165.     define blockStart
  166.     define notOk := 0                                                    # assume will pass all tests                                            
  167.     
  168.     endZone := thisZonePtr^^  & $00ffffff                    # yields size of zone trailer block 
  169.     endZone := thisZoneptr^ + endZone                            # pointer to zone trailer block plus its length is address of last byte in zone.
  170.     blockSize := ((thisBlockHndl^ & $00ffffff) - 8)^ & $00ffffff    #mask MP high byte, backup 8 to block header, mask tag byte        
  171.     if blockSize = 0 then                                             # check block size
  172.         "\n## block has an invalid NIL size"                    
  173.         notOk := 1
  174.     elseif blockSize & $01 =  1 then                            # (if size is zero it can't also be odd so don't bother to check.)
  175.         "\n## block has an invalid odd size"
  176.         notOk := 1
  177.     end
  178.     blockStart := thisBlockHndl^ & $00ffffff                # check block location 
  179.     if blockStart < thisZonePtr || blockStart > endZone then
  180.         if thisZonePtr = TheZone then
  181.             "\n## resource map's handle for this block yields a starting address outside of expected location in TheZone"
  182.         elseif thisZonePtr = SysZone
  183.             "\n## resource map's handle for this block yields a starting address outside of expected location in SysZone"
  184.         else
  185.             "\n##resource map's handle for this block yields a starting address outside of TheZone or SysZone" 
  186.         end
  187.         printf("start zone %.8x - end zone %.8x - block start %.8x\n", thisZonePtr, endZone, blockStart)
  188.         notOk := 1
  189.     elseif blockStart + blockSize > endZone then
  190.         "\n## block's size extends it beyond the end of this heap zone"
  191.         printf("block start %.8x - block size %.8x - end zone %.8x\n", blockStart, blockSize, endZone)
  192.         notOk := 1
  193.     end    
  194.     return notOk
  195. end # proc BlockInZone
  196.  
  197.  
  198. func CheckRes (typeListPtr, thisZone)
  199.     # func returns 1 if notOk and 0 if all is well
  200.     # locates master pointer in resMap for all loaded resources, then checks each MP and resource for validity
  201.     # and prints diagnostic information for the resource if a problem is found
  202.  
  203.     define refListPtr, thisResEntry
  204.     define numTypes, numThisType
  205.     define typeLoop, resLoop
  206.     define resZone, resHndl, resPtr
  207.     define resAttributes, resId, nameOffset
  208.     define notOk 
  209.     
  210.     numTypes := ^Word (TypeListPtr)    ^                    
  211.     for typeLoop := 0 to NumTypes                                        # for each resource type 
  212.          ThisResEntry := typeListPtr + 2 + typeLoop * 8                                
  213.         numThisType := ^Word(thisResEntry + 4)^                    # find how many of this type         
  214.         refListPtr := ^Word(thisResEntry + 6)^                     # and the start of the reference list for this type 
  215.         refListPtr := typeListPtr + refListPtr                
  216.         for resLoop := 0 to numThisType                                
  217.             resHndl := (refListPtr + 8)^                                                                    
  218.             if resHndl = 0 then
  219.                 resPtr := 0
  220.             else
  221.                 resPtr := resHndl^ & $00ffffff                         # get pointer to resource    
  222.             end                                                                        # check only loaded resources
  223.             if resPtr <> 0 then                                                # (a non-zero handle could point to NIL MP if resource was purged)
  224.                 resAttributes := refListPtr + 4                            
  225.                 resAttributes :=  ^Byte (resAttributes)^            # which heap is resource in?
  226.                 if resAttributes & $0040 then                             # if resSysHeap attribute set 
  227.                     resZone := SysZone                                        # then the resource should be in loaded in the System heap.
  228.                 else                                                                     # else it should be loaded in the current App's heap.
  229.                     resZone := TheZone
  230.                 end
  231.                 notOk := BlockInZone(resHndl,resZone)                #     master pointer to resource should be in this heap            
  232.                 notOk := CheckMp(resHndl, thisZone)                    # where this heap is app heap unless resfile is system's
  233.                 if notOk then                                                        # an error was reported
  234.                     resId := ^Word (refListPtr)^                            # give ID and name for the problem resource 
  235.                     printf("\n      ID: % .5d", resId)
  236.                     nameOffset := ^Word(refListPtr+2)^
  237.                     if nameOffset <> -1 then
  238.                         resName(nameOffset)
  239.                     end  
  240.                 end    # notOk        
  241.             end   # resPtr <> 0
  242.             refListPtr := refListPtr + 12                                # move on to test next resource in reference list
  243.         end #  resLoop                                                            # till all resources of this type are tested
  244.     end    # typeLoop                                                            # then test next resource type 
  245.     return notOk
  246. end    # proc CheckRes
  247.  
  248.  
  249. proc ResVerify 
  250.     # verifies all resource maps in the resource chain and all loaded resources (see CheckMP and BlockInZone for details)
  251.     # prints diagnostics if a problem is found
  252.     # reports as an error the case where a resource's attributes indicate it will load in the System heap but 
  253.     # the resource is loaded in the application heap anyway because the System heap doesn't have the space
  254.     # (we might want to get fancy at some point and verify that all offsets calculated for tracing the resource map are
  255.     # still within the map, but i figure if we get there the offsets must have been ok.)
  256.  
  257.     # Global Variables:
  258.     define global NEXTresFile                                                # pointer to top of current resource map
  259.  
  260.     define thisZone
  261.     define FileRef                            
  262.     define typeListOffset
  263.     define nextResHndl := topMapHndl     
  264.     define notOk 
  265.         
  266.     "\nVerifying the Resource Chain:"
  267.     repeat
  268.         NEXTresFile := nextResHndl^                # (this guy is global - for use in ResName, which is called from CheckRes)            
  269.         fileRef := ^Word(NEXTresFile+20)^
  270.         printf("\nResource map at: %.8X   File ref num: %X\n", NEXTresFile, fileRef)
  271.         fileName(fileRef)        
  272.         if fileRef = 2 then                                # System resource map and master pointers should be in the System heap
  273.             thisZone := SysZone                        # all other resource maps and master pointers should be in the current App heap
  274.         else                                                    
  275.             thisZone := TheZone    
  276.         end
  277.         notOk := CheckMp(nextResHndl, thisZone)        
  278.         typeListOffset := ^Word(NEXTresFile + 24)^
  279.         notOk := CheckRes (NEXTresFile + typeListOffset, thisZone)
  280.         if ! notOk then
  281.             "\nlooking good!"
  282.         end
  283.         nextResHndl := (NEXTresFile + 16)^  # check next resource map
  284.     until (nextResHndl = 0)                            # until no more resource maps to check
  285.     undefine NEXTresFile
  286. end    # proc ResVerify
  287.